//
//  CMSChartsMarker.swift
//  CMSCharts
//
//  Created by 吴演 on 2023/3/6.
//

import Foundation
import Charts

open class CMSChartsMarkerLink:NSObject {
    
    @objc open var charts:[ChartViewBase]?
    
    @objc open var bottomMarkerChart:ChartViewBase? {
        willSet {
            charts?.forEach({ chart in
                if let maker = chart.marker, maker is CMSChartsMarker,
                   let cmsMaker = maker as? CMSChartsMarker {
                    cmsMaker.showBottomLabel = (newValue == chart)
                }
            })
        }
    }
    
    @objc public init(charts: [ChartViewBase]? = nil, bottomMarkerChart: ChartViewBase? = nil) {
        self.charts = charts
        self.bottomMarkerChart = bottomMarkerChart
    }
    
}

open class CMSChartsMarker: MarkerImage
{
    @objc open var color: UIColor
    @objc open var font: UIFont
    @objc open var textColor: UIColor
    @objc open var insets: UIEdgeInsets
    @objc open var minimumSize = CGSize()
    
    @objc static let left = "left"
    @objc static let right = "right"
    @objc static let bottom = "bottom"
    @objc static let all: [String] = [left, right, bottom]
    
    var directoins:[MarkerItem] = []
    
    @objc open var showBottomLabel: Bool = false {
        didSet {
            if let dir = directoins.first(where: { $0.direction == .bottom}) {
                dir.show = showBottomLabel
            }
        }
    }
    
    fileprivate var hightLightT :Highlight!
    
    var drawClosure:((Highlight)->Void)?
    
    @objc public init(color: UIColor, font: UIFont, textColor: UIColor, insets: UIEdgeInsets)
    {
        self.color = color
        self.font = font
        self.textColor = textColor
        self.insets = insets
        super.init()
        directoins = CMSChartsMarker.all.map { dir in
            let mark = MarkerItem.stringToDirection(string: dir)
            mark.label = labelOfCommon()
            return mark}
    }
    
    // 更新坐标
    open override func refreshContent(entry: ChartDataEntry, highlight: Highlight)
    {
        hightLightT = highlight
        directoins.forEach { marker in
            marker.setupLabel(highlight: highlight)
        }
    }
    
    // 开始绘制
    open override func draw(context: CGContext, point: CGPoint)
    {
        directoins.forEach { direction in
            if let label =  direction.label, label.superview == nil{
                chartView?.addSubview(label)
            }
            direction.rectX(chartView: chartView, viewPortHandler: (chartView?.viewPortHandler!)!, hightLightT: hightLightT)
        }
    }
    
    // charts绘制代理回调
    public func shouldCallDrawOutOfBounds() -> Bool {
        return true
    }
    
    public func disappear(context: CGContext) {
        directoins.forEach { marker in
            marker.removeView()
        }
    }
    
    @objc func labelOfCommon() -> UILabel{
        self.size = CGSize(width: 30, height: 10)
        let l = UILabel.init(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        l.font = self.font
        l.textColor = self.textColor
        l.backgroundColor = UIColor.darkGray
        l.textAlignment = .center
        return l
    }
}


enum Direction:String, CaseIterable {
    case left
    case right
    case bottom

    static func stringToDirection(string: String) -> Direction{
        return Direction(rawValue: string) ?? .left
    }
}

class MarkerItem {
    var direction:Direction
    var labelSize:CGSize
    var show:Bool = true
    public var label:UILabel?
    static func stringToDirection(string: String) -> MarkerItem{
        return MarkerItem(direction: Direction.stringToDirection(string: string), labelSize: CGSize.zero, show: true)
    }
    
    init(direction: Direction, labelSize: CGSize, show: Bool, label: UILabel? = nil) {
        self.direction = direction
        self.labelSize = labelSize
        self.show = show
        self.label = label
    }
    
    func removeView(){
        label?.isHidden = true
    }
    
    func rectX(chartView:ChartViewBase?, viewPortHandler:ViewPortHandler, hightLightT:Highlight) {
        if !show {
            return
        }
        var rect:CGRect = CGRect.zero
        switch direction {
        case .left, .right:
            let contentTop = chartView?.viewPortHandler?.contentTop
            let contentBottom = chartView?.viewPortHandler?.contentBottom
            if (hightLightT.touchPoint.y - 1 <= contentTop! || hightLightT.touchPoint.y + 1 >= contentBottom!) {
                removeView()
                break
            }
            var x:CGFloat = 0
            if direction == .left {
                x = 10
            } else {
                let contentRight = chartView?.viewPortHandler?.contentRight ?? 0
                x = contentRight - self.labelSize.width
            }
            var y = hightLightT.touchPoint.y - labelSize.height/2.0
            y = max(contentTop!, y)
            y = min(contentBottom! - self.labelSize.height , y)
            
            rect = CGRect(
                origin: CGPoint(
                    x: x,
                    y: y),
                size: self.labelSize)
            label?.frame = rect
            label?.isHidden = false
            break
            
        case .bottom:
            let contentLeft = chartView?.viewPortHandler?.contentLeft
            let contentRight = chartView?.viewPortHandler?.contentRight
            
            var x = hightLightT.drawX - self.labelSize.width/2.0
            x = max(contentLeft!, x)
            x = min(contentRight! - self.labelSize.width , x)
            
            rect = CGRect(
                origin: CGPoint(
                    x: x,
                    y: (chartView?.viewPortHandler.contentBottom)!),
                size: self.labelSize)
            label?.frame = rect
            label?.isHidden = false
            break
        }
    }
    
     func setupLabel(highlight:Highlight) {
        if show {
            var content = ""
            var height:CGFloat = 15
            var width:CGFloat = 60
            switch direction {
            case .left, .right:
                content = String(format: "%.2f", highlight.touchValueY)
                break
            case .bottom:
                content = String(format: "%.2f", highlight.x)
                height = 10
                width = 70
                break
            }
            if let label = label {
                label.text = content
                self.labelSize = CGSize(width: width, height: height)
            }
        }
    }
}
